﻿using System;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Sockets;

namespace xxpl.DNS
{
    public class DnsHelper
    {
        private static readonly string[] hosts = ConfigurationManager.AppSettings["GAEAPP"].Split(',');
        private static readonly string https = ConfigurationManager.AppSettings["GAEHTTPS"];
        private static readonly string http = ConfigurationManager.AppSettings["GAEHTTP"];
        private static readonly string ipv6 = ConfigurationManager.AppSettings["GAEIPV6"];
        private static readonly string use = ConfigurationManager.AppSettings["Use"];
        private static IPAddress googleHost;

        public static void Init()
        {
            IPAddress ipAddress;
            if (!string.IsNullOrEmpty(https)
                && (string.IsNullOrEmpty(use) || use == "GAEHTTPS"))
            {
                string[] ips = https.Split('|');

                foreach (string ip in ips)
                {
                    if (!IPAddress.TryParse(ip, out ipAddress))
                    {
                        IPAddress[] ipAddresses = Dns.GetHostAddresses(ip);
                        if (ipAddresses.Any(address => TestAccessbility(address, hosts[0], true))) break;
                    }
                    else
                    {
                        if (TestAccessbility(ipAddress, hosts[0], true)) break;
                    }
                }
            }

            if (googleHost == null
                && !string.IsNullOrEmpty(http)
                && (string.IsNullOrEmpty(use) || use == "GAEHTTP"))
            {
                string[] ips = http.Split('|');

                foreach (string ip in ips)
                {
                    if (!IPAddress.TryParse(ip, out ipAddress))
                    {
                        IPAddress[] ipAddresses = Dns.GetHostAddresses(ip);
                        if (ipAddresses.Any(address => TestAccessbility(address, hosts[0], false))) break;
                    }
                    else
                    {
                        if (TestAccessbility(ipAddress, hosts[0], false)) break;
                    }
                }
            }

            if (googleHost == null && !string.IsNullOrEmpty(ipv6))
            {
                ipAddress = IPAddress.Parse(ipv6);

                if (!TestAccessbility(ipAddress, hosts[0], true))
                {
                    TestAccessbility(ipAddress, hosts[0], false);
                }
            }
        }

        private static bool TestAccessbility(IPAddress ipAddress, string host, bool useHttps)
        {
            try
            {
                string url = (useHttps ? "https://" : "http://") + (ipAddress.AddressFamily == AddressFamily.InterNetworkV6 ? "[" + ipAddress + "]" : ipAddress.ToString());
                HttpWebRequest requestToProxy = (HttpWebRequest)WebRequest.Create(url + "/xpp");
                requestToProxy.Host = host;
                requestToProxy.Proxy = null;
                requestToProxy.Timeout = 5000;
                requestToProxy.AllowAutoRedirect = false;

                HttpWebResponse response = (HttpWebResponse)requestToProxy.GetResponse();
                response.Close();
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    googleHost = ipAddress;
                    return true;
                }
                return false;
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} - unavailable, https={1}", ipAddress, useHttps);
                return false;
            }
        }

        public static IPAddress GetHost()
        {
            return googleHost;
        }

        public static string GetGaeHost(string url)
        {
            return hosts[Math.Abs(url.GetHashCode() % hosts.Length)];
        }
    }
}
